<?php
$MSDB_AdoDBPath = 'adodb/adodb.inc.php';
$MSDB_DBMSType = 'odbc_mssql';
$MSDB_ConnectionString = "Driver={SQL Server};Server=DIRIENZO, 1433;Database=MyMorty;";	
$MSDB_Username = 'sa';
$MSDB_Password = 'dbo';


define("MSDB_Varchar","Varchar",false);
define("MSDB_Integer","Integer",false);
define("MSDB_Bit","Bit",false);
define("MSDB_Text","Text",false);
define("MSDB_DateTime","DateTime",false);


include_once("DBValidators.php");


class MSDBEntity {
	
}


class MSDBField {
	var $Name;
	var $ValidationTitle;
	var $Type;
	var $StringMaxLength;
	var $StringMinLength;
	var $IntLow;
	var $IntHigh;
	var $AllowsNull;
	var $InsertField;
	var $UpdateField;
	var $isPK;
	var $Validators;
	
	function MSDBField() {
		$this->Name="";
		$this->Type="";
		$this->ValidationTitle="";
		$this->StringMinLength=-1;
		$this->StringMaxLength=-1;
		$this->IntLow=-1;
		$this->IntHigh=-1;
		$this->AllowsNull=true;
		$this->InsertField=true;
		$this->UpdateField=true;
		$this->isPK=false;
		$this->Validators = array();
	}
	
	function addValidator(&$validaror) {
		$this->Validators[] = &$validaror;
	}
}


class MSDBTable {
	var $TableName;
	var $Fields;
	
	function MSDBTable($tableName) {
		$this->TableName = $tableName;
		$this->Fields = array();
	}
	
	function setPK($fieldName) {
		$fld = &$this->getField($fieldName);
		if ($fld!=null) {
			$fld->isPK = true;
		}
	}
	
	function &getField($fieldName) {
		return $this->Fields[$fieldName];
	}
	
	function &getPKField() {
		foreach ($this->Fields as $fld) {
			if ($fld->isPK)
				return $fld;
		}
		return null;
	}
	
	function &addField($name, $ValidationTitle, $type, $minLength=-1, $maxLength=-1,$allowsNull=true,$insert=true,$update=true) {
		$tmp = new MSDBField();
		$tmp->Name = $name;
		$tmp->ValidationTitle = $ValidationTitle;
		$tmp->Type = $type;
		$tmp->AllowsNull = $allowsNull;
		$tmp->InsertField = $insert;
		$tmp->UpdateField = $update;

		$this->Fields[$name] = &$tmp;
		
		return $tmp;
	}
	
	function &addVarcharField($name, $ValidationTitle, $minLength=-1, $maxLength=-1,$allowsNull=true,$insert=true,$update=true) {
		$tmp = &$this->addField($name, $ValidationTitle, MSDB_Varchar, $minLength, $maxLength, $allowsNull, $insert, $update);
		$tmp->StringMinLength = $minLength;
		$tmp->StringMaxLength = $maxLength;
		
		return $tmp;
	}
	
	function &addIntField($name, $ValidationTitle, $intLow=-1, $intHigh=-1,$allowsNull=true,$insert=true,$update=true) {
		$tmp = &$this->addField($name, $ValidationTitle,  MSDB_Integer, -1, -1, $allowsNull, $insert, $update);
		$tmp->IntLow = $intLow;
		$tmp->IntHigh = $intHigh;

		return $tmp;
	}
	
	function &addBitField($name, $ValidationTitle, $allowsNull=true,$insert=true,$update=true) {
		$tmp = &$this->addField($name, $ValidationTitle, MSDB_Bit, -1, -1, $allowsNull, $insert, $update);

		return $tmp;
	}
	
	function &addDateField($name, $ValidationTitle, $allowsNull=true,$insert=true,$update=true) {
		$tmp = &$this->addField($name, $ValidationTitle, MSDB_DateTime, -1, -1, $allowsNull, $insert, $update);

		return $tmp;
	}
}



class MSDBCommon {
	var $request;
	var $table;
	var $quoteFix;
	var $connection;
	
	function fieldIsString($Field) {
		return ($Field->Type == MSDB_Text) || ($Field->Type == MSDB_Varchar) || ($Field->Type == MSDB_DateTime);
	}
	
	function MSDBCommon(&$req, &$MSDBtable) {
		$this->quoteFix = "''";
		$this->request = &$req;
		$this->table = &$MSDBtable;
	}

	function setConnection(&$conn) {
		$this->connection = &$conn;
	}
	
	function &getConnection() {
		//If there is no connection we create it
		if ($this->connection==null)
			$this->Connect();
			
		return $this->connection;
	}
	
	function Connect() {
		global $MSDB_AdoDBPath;
		global $MSDB_DBMSType;
		global $MSDB_ConnectionString;
		global $MSDB_Username;
		global $MSDB_Password;

		require_once($MSDB_AdoDBPath); 
		
		$conn =&ADONewConnection($MSDB_DBMSType);
		$conn->Connect($MSDB_ConnectionString,$MSDB_Username,$MSDB_Password);
		$conn->SetFetchMode(ADODB_FETCH_ASSOC); 
		$this->setConnection($conn);
	}

	function CloseConnection() {
		$this->connection->Close();
	}

	
	function &getEntity($tableName, $fieldName, $Value = "", $isString = false) {
		$val = ($Value!="" ? $Value : $this->request[$fieldName]);
		if ($isString) {
			$val = "'" . $this->fixQuotes($val) . "'";
		}
		elseif (!$this->checkInt($val)) {
			$val = 0;
		}
		
		$sql = "SELECT * from " . $tableName . " WHERE " . $fieldName . "=" . $val;
		
		$conn = &$this->getConnection();
		$rs = $conn->Execute($sql); 
		
		if (!$rs) 
			die("[ERROR WHILE TRYING TO CONNECT TO THE DB] " . $conn->ErrorMsg()); 
		
		$ret = &new MSDBEntity();
		if (!$rs->EOF) {
			foreach ($rs->fields as $col=>$val) {
				$ret->$col = $val;
			}
		}
			
		$this->CloseConnection();
		
		return $ret;
	}
	
	
	
	function fixQuotes($data){
		return str_replace("'",$this->quoteFix,$data);
	}
	
	function checkInt($data){
		$ret=(is_numeric($data)?$data:0);
		return $ret;
	}
	
	function checkBit($data) {
		return (($data=="1") || ($data=="true")?"1":"0");
	}
	
	function getUpdateString($AlsoWhere="") {
		$flds = "";
		foreach ($this->table->Fields as $fld) {
			if (($fld->UpdateField) && (!$fld->isPK)) {
				
				if ($fld->AllowsNull && ($this->request[$fld->Name] == ""))
						$flds .= $fld->Name . "=NULL,";
				else {
					if ($this->fieldIsString($fld))
						$flds .= $fld->Name . "='" . $this->fixQuotes($this->request[$fld->Name]) . "',";
					elseif ($fld->Type==MSDB_Bit) {
						$flds .= $fld->Name . "=" . $this->checkBit($this->request[$fld->Name]) . ",";
					}
					else {
						if ($this->request[$fld->Name] == "")
							$flds .= $fld->Name . "=0,";
						else
							$flds .= $fld->Name . "=" . $this->checkInt($this->request[$fld->Name]) . ",";
					}
				}
					
			}
		}
		$flds = substr($flds,0,strlen($flds)-1);
		
		
		
		$pkWhere = "";
		$tmpPK = &$this->table->getPKField();
		
		if ($tmpPK!=null) {
			if ($this->fieldIsString($tmpPK))
				$pkWhere = $tmpPK->Name . "='" . $this->fixQuotes($this->request[$tmpPK->Name]) . "'";
			else
				$pkWhere = $tmpPK->Name . "=" . $this->checkInt($this->request[$tmpPK->Name]);
		}

				
				
		$ret = "UPDATE " . $this->table->TableName . " SET " . $flds;

		if ($pkWhere!="") {
			$ret .= " WHERE " . $pkWhere;
			if ($AlsoWhere!="")
				$ret .= " AND " . $AlsoWhere;
		}
		elseif ($AlsoWhere!="")
			$ret .= " WHERE " . $AlsoWhere;
			
		
		return $ret;
	}
	

	
	function getInsertString() {
		$flds = "";
		$fldsValues = "";
		foreach ($this->table->Fields as $fld) {
			if ($fld->InsertField) {
				
				$flds .= $fld->Name . ",";
				
				if ($fld->AllowsNull && ($this->request[$fld->Name] == ""))
						$fldsValues .= "NULL,";
				else
					if ($this->fieldIsString($fld))
						$fldsValues .= "'" . $this->fixQuotes($this->request[$fld->Name]) . "',";
					elseif ($fld->Type==MSDB_Bit)
						$fldsValues .= $this->checkBit($this->request[$fld->Name]) . ",";
					else
						if ($this->request[$fld->Name] == "")
							$fldsValues .= "0,";
						else
							$fldsValues .= $this->checkInt($this->request[$fld->Name]) . ",";
					
			}
		}
		$flds = substr($flds,0,strlen($flds)-1);
		$fldsValues = substr($fldsValues,0,strlen($fldsValues)-1);
		
		$ret = "INSERT INTO " . $this->table->TableName . "(" . $flds . ") VALUES (" . $fldsValues . ")";
		
		return $ret;
	}
	
	
	
	
	
	function insert() {
		$conn = &$this->getConnection();
		if ($conn->Execute($this->getInsertString()) === false) {
			$ret = "[ERROR ON INSERT] " . $conn->ErrorMsg();
		}
		else 
			$ret = true;
			
		$this->CloseConnection();
		
		return $ret;
	}
	
	function update() {
		$conn = &$this->getConnection();
		if ($conn->Execute($this->getUpdateString()) === false) {
			$ret = "[ERROR ON UPDATE] " . $conn->ErrorMsg();
		}
		else 
			$ret = true;
			
		$this->CloseConnection();
		
		return $ret;
	}
	
	

	
    function &getRecordset($table, $where="", $orderby="", $rows=-1, $offset=-1){
        $sql = "SELECT * FROM ".$table." ";
        if($where!="") $sql .= " WHERE " . $where;
        if($orderby!="") $sql .= " ORDER BY " . $orderby;
    
		$conn = &$this->getConnection();
        $recordSet = $conn->SelectLimit($sql, $rows, $offset);

    	$this->CloseConnection();
		return $recordSet;
    }
    
    
    function getRecordsetCount($table, $where=""){
        $sql = "SELECT COUNT(*) AS cnt FROM ".$table." ";
        if($where!="") $sql .= " WHERE " . $where;

		$conn = &$this->getConnection();
        $recordSet = $conn->Execute($sql);

		$this->CloseConnection();
        
        return $recordSet->fields['cnt'];
    }
    
	
	
	function validateFieldsForInsert() {
		return $this->validateFields(true);
	}

	function validateFieldsForUpdate() {
		return $this->validateFields(false);
	}

	
	function validateFields($forInsert) {
		$err=array();
		
		foreach ($this->table->Fields as $fld) {

			//Do not validate the field if it is not included in the operation
			if ($forInsert && !$fld->InsertField) 
				continue;
			if ($forUpdate && !$fld->UpdateField) 
				continue;
			
				
			
			if ((!$fld->AllowsNull) && ($this->request[$fld->Name]==""))
				$err[] = "Specify a value for $fld->ValidationTitle";

				
				
			if ($this->request[$fld->Name]!="") {
				//If the field has a value run the custom validators if any
				foreach ($fld->Validators as $v) {
					if (!$v->isValid($fld, $this->request[$fld->Name])) {
						$err[] = $v->getError();
					}
				}
			}
				
				
			switch ($fld->Type) {
				case MSDB_Integer:
					if (($this->request[$fld->Name]!="") && (!is_numeric($this->request[$fld->Name])))
							$err[] = "The value for $fld->ValidationTitle is invalid";
					else {
						if (($fld->IntLow!=-1) && ($this->request[$fld->Name]!=""))
							if ($this->request[$fld->Name] < $fld->IntLow)
								$err[] = "The minimum value allowed for $fld->ValidationTitle is $fld->IntLow";
						
						if (($fld->IntHigh!=-1) && ($this->request[$fld->Name]!=""))
							if ($this->request[$fld->Name] > $fld->IntHigh)
								$err[] = "The maximum value allowed for $fld->ValidationTitle is $fld->IntHigh";
					}
					break;

			
				case MSDB_Varchar:
				case MSDB_Text:
					if (($fld->StringMinLength!=-1) && ($this->request[$fld->Name]!=""))
						if (strlen($this->request[$fld->Name]) < $fld->StringMinLength)
							$err[] = "The minimum length for $fld->ValidationTitle is $fld->StringMinLength";

					if (($fld->StringMaxLength!=-1) && ($this->request[$fld->Name]!=""))
						if (strlen($this->request[$fld->Name]) > $fld->StringMaxLength)
							$err[] = "The maximum length for $fld->ValidationTitle is $fld->StringMaxLength";

					break;
			}
			
		}
		
		return $err;
	}
}

